#!/usr/bin/env python3 
'''
    Dom 处理工程文件 
    Dom for cbp
    Do_index=1:创建工程文件，传入 文件名称 
'''

import os
import xml.dom.minidom as Dom
class Dom4cbp:
    Max_id = 0
    def __init__(self,parent,  cbp_Name):
        self.parent = parent    #主窗口作为父窗口传参，方便利用“信息输出视图”显示异常情况
        if self.Max_id == 1:
            self.parent.text_browser.append('工程 已存在！') 
            return
        self.cbpName = cbp_Name
        [self.dirname,self.filename]=os.path.split(self.cbpName)
        if not self.filename :
            self.Max_id = 1
    '''     使用DOM类操作xml文件，改动一次总会产生很多空行，用下面的函数来消除多余的空行。
    '''
    def filterBlankLine(self, filePath):
        if filePath is None or os.path.exists(filePath)==False:
            self.parent.text_browser.append('读入工程文件出错！') 
            return
        with open(filePath,'r+',encoding='utf-8') as fo:
            str0 = (fo.read())
            fo.close()
            deststr=''
            for rec in str0.splitlines():
                if len(rec) == 0:
                    continue
                for i in range(len(rec)):
                    if rec[i] == '\t':
                        continue
                    else:
                        deststr += rec
                        deststr +='\n'
                        break
        with open(filePath,'w+',encoding='utf-8') as fo:
            fo.write(deststr)
            fo.close()
    def CreatNewCbp(self):             
        doc = Dom.Document() 
        #1.root = CodeBlocks_project_file
        root_node = doc.createElement("CodeBlocks_project_file") 
        doc.appendChild(root_node)   
        #2.创建root的2个子项  FileVersion  Project
        FileVersion_node = doc.createElement("FileVersion")
        FileVersion_node.setAttribute("major", "1")  
        FileVersion_node.setAttribute("minor", "6")  
        root_node.appendChild(FileVersion_node)
        
        Project_node = doc.createElement("Project")
        root_node.appendChild(Project_node)
        #3.1增加project 子项 3个Option 
        Option_node1 = doc.createElement("Option")  
        Option_node1.setAttribute("title",os.path.splitext(self.filename)[0])
        Option_node2 = doc.createElement("Option")  
        Option_node2.setAttribute("pch_mode","2")
        Option_node3 = doc.createElement("Option")  
        Option_node3.setAttribute("compiler","sdcc")
     
        Project_node.appendChild(Option_node1)
        Project_node.appendChild(Option_node2)
        Project_node.appendChild(Option_node3)
        
        #3.2增加project 子项 Compiler    
        FileVersion_node = doc.createElement("Compiler")
            #3.2.1增加Compiler子项2个Add
        Option_node1 = doc.createElement("Add")  
        Option_node1.setAttribute("option","--mmcs51")
        Option_node2 = doc.createElement("Add")  
        Option_node2.setAttribute("option","--model-small")
        FileVersion_node.appendChild(Option_node1)
        FileVersion_node.appendChild(Option_node2)    
        Project_node.appendChild(FileVersion_node)
        #3.3增加project 子项  Linker    
        FileVersion_node = doc.createElement("Linker")
            #3.3.1增加Linker子项    4个Add 
        Option_node1 = doc.createElement("Add")  
        Option_node1.setAttribute("option","--xram-size 4096")
        Option_node2 = doc.createElement("Add")  
        Option_node2.setAttribute("option","--iram-size 256")
        Option_node3 = doc.createElement("Add")  
        Option_node3.setAttribute("option","--code-size 65536")
        Option_node4 = doc.createElement("Add")  
        Option_node4.setAttribute("option","--out-fmt-ihx")
        FileVersion_node.appendChild(Option_node1)
        FileVersion_node.appendChild(Option_node2)    
        FileVersion_node.appendChild(Option_node3)
        FileVersion_node.appendChild(Option_node4)    
        Project_node.appendChild(FileVersion_node)         
        # 4.准备完毕，信息写人.cbp文件
        try:
            with open(self.cbpName,'w',encoding='UTF-8') as fh:
                # writexml()第一个参数是目标文件对象，第二个参数是根节点的缩进格式，第三个参数是其他子节点的缩进格式，
                # 第四个参数制定了换行格式，第五个参数制定了xml内容的编码。
                doc.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
                fh.close()
                #print('写入xml OK!')
        except Exception as err:
            self.parent.text_browser.append('创建.cbp工程文件失败！') 
    def delectFileFromCbp(self, _fileName):#所有文件名都在Unit 中
        if not self.cbpName or os.path.exists(self.cbpName)==False:
            self.parent.text_browser.append('%s 工程文件不存在！'%self.cbpName) 
            return
        doc=Dom.parse(self.cbpName)
        # 1.获取根节点
        root=doc.documentElement
        #2.读取根节点下面所有名字为Project的一级节点
        Projects=root.getElementsByTagName('Project')#实际上只有一个Project节点
        #3.读取Project节点下，所有名字为“Unit”的二级节点
        Options = Projects[0].getElementsByTagName('Unit')
        for Option in Options:
            #4.判断属性值是否包含目标文件名，如果是，将该节点删除
            if _fileName in Option.getAttribute('filename')  :
                Option.parentNode.removeChild(Option)
                #5.更新工程文件
                try:
                    with open(self.cbpName,'w',encoding='UTF-8') as fh:
                        doc.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
                        fh.close()
                        self.filterBlankLine(self.cbpName)
                except :
                    self.parent.text_browser.append('在.cbp工程文件中删除 <%s>失败！' % _fileName) 
                break

    def AddFile2cbp(self, fullfile):    
        if not self.cbpName or os.path.exists(self.cbpName)==False:
            self.parent.text_browser.append('%s 工程文件不存在！'%self.cbpName) 
            return        
        doc=Dom.parse(self.cbpName)
        # 1.获取根节点
        root=doc.documentElement
        #2.读取根节点下面所有名字为Project的一级节点
        Options=root.getElementsByTagName('Project')
        
        [dirname,filename]=os.path.split(fullfile)  #判断文件是否在工程目录下        
        if self.dirname not in fullfile:
            self.parent.text_browser.append("所添加的文件不在工程目录下，添加失败！")
            return
        if dirname != self.dirname: #文件位于工程目录下，但是路径不完全相等，说明文件位于子文件夹里面
            filename = fullfile[len(self.dirname)+1:]
        #3.生成属性值为该文件名的 “Unit”项，添加到Project节点上
        Uint_node = doc.createElement("Unit")  
        Uint_node.setAttribute("filename",filename)
        Options[0].appendChild(Uint_node)
        #4.更新工程文件
        try:
            with open(self.cbpName,'w',encoding='UTF-8') as fh:
                doc.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
                fh.close()
                self.filterBlankLine(self.cbpName)
        except Exception as err:
             self.parent.text_browser.append('在.cbp工程文件中添加 <%s>失败！' % filename) 
    def SetOptionOfXram(self, _xdata):#在工程文件中修改"Option_node1"  "--xram-size 4096"
        if not self.cbpName or os.path.exists(self.cbpName)==False:
            self.parent.text_browser.append('%s 工程文件不存在！'%self.cbpName) 
            return
        doc=Dom.parse(self.cbpName)
        # 1.获取根节点
        root=doc.documentElement
        #2.读取根节点下面所有名字为Project的一级节点
        Projects=root.getElementsByTagName('Project')
        #3.读取Project节点下，所有名字为“Add”的二级节点
        Options = Projects[0].getElementsByTagName('Add')
        for Option in Options:
            #4.查找“Add”节点中，属性值包含 --xram 的节点，设置为参数中的 _xdata
            if '--xram' in Option.getAttribute('option')  :
                value = '--xram-size '+_xdata
                Option.setAttribute("option",value)
                #5.更新工程文件
                try:
                    with open(self.cbpName,'w',encoding='UTF-8') as fh:
                        doc.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
                        fh.close()
                        self.filterBlankLine(self.cbpName)
                except :
                    self.parent.text_browser.append('在.cbp工程文件中设置 %s 参数失败！' % value) 
                break
    def getFileList_xdata_In_cbp(self):
        if not self.cbpName or os.path.exists(self.cbpName)==False:
            self.parent.text_browser.append('%s 工程文件不存在！'%self.cbpName) 
            return None
        fileList=[]
        _xdata=''
        doc=Dom.parse(self.cbpName)
        #1. 获取根节点
        root=doc.documentElement
        #2.读取根节点下面所有名字为Project的一级节点
        Projects=root.getElementsByTagName('Project')
        #3.读取Unit 即包含文件名的项
        Options = Projects[0].getElementsByTagName('Unit')
        for Option in Options:
            _fileName = Option.getAttribute('filename')  
            if _fileName !=None:
                fileList.append(self.dirname+'/'+ _fileName)
        #4.找到 --xram-size ，获取需要的参数        
        Options = Projects[0].getElementsByTagName('Add')
        for Option in Options:
            str1 = Option.getAttribute('option')
            if 'xram' in str1:
                _xdata = str1[-4:]
                break
        if len(_xdata) <2:  #如果没有读到该参数，赋给默认值
            _xdata = '8192'
        return fileList, _xdata
